Lambda表达式,CPP必须了解的特性

女儿叫老白 2020-04-17 12:51:53

C++11版本发行已经几年了,许多老项目也切换到C++11版本,而在实际开发中,很多程序员由于不熟悉C++11版本的匿名函数 Lambda表达式 ,也依旧产生着大量冗余,杂乱的代码。

一、旧的表达

在以前,针对排序的比较函数,我们只能写一个cmp函数。

bool cmp(int a,int b)
{
    return a < b;
}
void test_sort(vector<int>& vec)
{
    sort(vec.begin(), vec.end(), cmp);
    printf("after sort cmp:\n");
    for(int i=0;i<10;i++)
    {
        printf("%d: %d\n", i, vec[i]);
    }
}

然而这个cmp函数只能在这个场景里使用,并且由于旧语法的限制,只能够定义一个全局函数,当需要多个cmp函数时,就显得异常凌乱。

二、新的表达

在C++11版本中,C++引入了匿名函数Lambda 表达式。

语法如下:

[capture list] (parameter list) ->return type 
{
    function body
}

其中第一个方括号代表闭包的特性,用来给匿名函数传递一些外部的变量。

大概分几类:

1、[] 不使用任何外部变量
2、[&] 所有变量都以引用形式使用
3、[=] 所有变量都以传值形式使用
4、[x, &y] x 以传值形式使用,y 以引用形式使用。
5、[&, x] x 以传值形式使用,其他的以引用形式使用。
6、[=, &z] z 以引用形式使用,其他的以传值形式使用。
7、[=, x, &y] 可以传入更多的参数

这样,我们就可以愉快的写匿名函数了。

sort(vec.begin(), vec.end(), [](int a, int b) -> bool
{
    return a > b;
})
printf("after sort lambda:\n");
for(int i=0;i<10;i++)
{
    printf("%d: %d\n", i, vec[i]);
}

三、实际应用

在现实生产中,我们经常会遇到协程,这里就用协程来举例。

我们知道协程的每个并发都需要按照框架实现一个之类,而且还需要实现一个虚函数,这个虚函数内还可以进行相关的网络操作。这样进行封装后,就可以实现并发的对外请求了。

代码如下:

class RealCoroutine : public BaseCoroutine
{
    public:
    int Process()
    {
        return netCoroutine();//业务的网络操作在这里进行
    }
}
void test_task()
{
    vector<BaseCoroutine> list;
    RealCoroutine* onr = new RealCoroutine();
    //对one的初始化
    list.push_back(one);
    RealCoroutine* two = new RealCoroutine();
    //对one的初始化
    list.push_back(two);
    exe_coroutine_list(list);
    //处理one的返回结果
    //处理two的返回结果
}

如上所示,由于是并发操作,请求分为两部分来处理,而并发逻辑一多时,整个代码就会非常的凌乱,难以维护。

而此时使用 lambda 函数封装,则简洁的多。

class LambdaCoroutineList
{
    public:
    void operator +=(const TaskFunc& f)
    {
        //...
    }
    int exe()
    {
        exe_coroutine_list(list);
    }
    private:
    vector<BaseCoroutine> list;
};
void test_lambda()
{
    LambdaCoroutineList list;
    list += []()
    {
        //对one的初始化
        netCoroutine();
        //处理one的返回结果
    };
    list += []()
    {
        //对two的初始化
        netCoroutine();
        //处理two的返回结果
    }
    list.exe();
}

这时候,只需要在一个匿名函数里面以同步的方式写整个代码逻辑即可。

本页共116段,2326个字符,3708 Byte(字节)